#include "dvDataTableController.h"

dvDataTableController::dvDataTableController()
{
}

dvDataTableController::~dvDataTableController()
{
    removeAllIndicators();
}

void dvDataTableController::insertIndicator(const DV_INDICATOR &indicator)
{
    dvDataPack* pack = NULL;
    if (!m_listIndicators.count())
    {
        pack = new dvDataPack;
        pack->indicator = indicator;
        m_listIndicators.push_back(pack);
    }
    else
    {
        int index = findIndicator(indicator.id);
        if (index == -1)
        {
            pack = new dvDataPack;
            pack->indicator = indicator;
            m_listIndicators.push_back(pack);
        }
        else
        {
            pack = m_listIndicators.at(index);
            pack->indicator = indicator;
        }
    }
}

bool dvDataTableController::removeIndicator(const QVariant &indicatorId)
{
    int index = findIndicator(indicatorId);
    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            delete pack;
        }
        m_listIndicators.removeAt(index);
        return true;
    }
    return false;
}

void dvDataTableController::removeAllIndicators()
{
    foreach(dvDataPack* pack, m_listIndicators)
    {
        if (pack)
        {
            delete pack;
        }
    }
    m_listIndicators.clear();
}

int dvDataTableController::findIndicator(const QVariant &indicatorId)
{
    int index = -1;
    for (int i = 0; i < m_listIndicators.count(); i++)
    {
        if (m_listIndicators.at(i)->indicator.id == indicatorId)
        {
            index  = i;
            break;
        }
    }
    return index;
}

bool dvDataTableController::insertData(const QVariant &indicatorId, const QString &date,
                                       const QVariant &regionId, const QVariant &value)
{
    bool result = false;

    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);

        bool isDateExist = false;

        for (int i = 0; i < pack->listDate.count(); i++)
        {
            if (date == pack->listDate.at(i))
            {
                isDateExist = true;
                break;
            }
        }

        if (isDateExist)
        {
            Data* data = pack->mapData.value(date);
            if (data)
            {
                data->insert(regionId.toInt(),value.toDouble());
                result = true;
            }
        }
        else
        {
            Data* data = new Data;
            data->insert(regionId.toInt(),value.toDouble());
            pack->mapData.insert(date, data);
            pack->listDate.push_back(date);
            result = true;
        }
    }

    return result;
}

bool dvDataTableController::changeData(const QVariant &indicatorId, const QString &oldDate,
                                       const QString &newDate, const QVariant& regionId,
                                       const QVariant &value)
{
    int index = findIndicator(indicatorId);

    if (index != -1 && oldDate != newDate &&
        !oldDate.isEmpty() && !newDate.isEmpty())
    {
        dvDataPack *pack = m_listIndicators.at(index);
        if (pack)
        {
            if (removeData(indicatorId, oldDate, regionId))
            {
                return insertData(indicatorId, newDate, regionId, value);
            }
        }
    }

    return false;
}

bool dvDataTableController::changeRegion(const QVariant &indicatorId, const QString &date,
                                         const QVariant &oldRegionId, const QVariant &newRegionId,
                                         const QVariant &value)
{
    int index = findIndicator(indicatorId);

    if (index != -1 && oldRegionId != newRegionId &&
        !oldRegionId.isNull() && !newRegionId.isNull())
    {
        dvDataPack *pack = m_listIndicators.at(index);
        if (pack)
        {
            if (removeData(indicatorId, date, oldRegionId))
            {
                if (isExistData(indicatorId, date, newRegionId))
                {
                    Refs* refs = pack->mapRefs.value(date, NULL);
                    if (refs && refs->value(newRegionId.toInt(), -1) != -1)
                    {
                        int refCount = refs->value(newRegionId.toInt());
                        refCount++;
                        refs->insert(newRegionId.toInt(), refCount);
                    }
                    else
                    {
                        refs = new Refs;
                        refs->insert(newRegionId.toInt(), 2);
                        pack->mapRefs.insert(date, refs);
                    }
                    //return true;
                }
                return insertData(indicatorId, date, newRegionId, value);
            }
        }
    }

    return false;
}

bool dvDataTableController::removeData(const QVariant &indicatorId, const QString &date,
                                       const QVariant &regionId)
{
    bool result = false;

    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);

        bool isDateExist = false;

        for (int i = 0; i < pack->listDate.count(); i++)
        {
            if (date == pack->listDate.at(i))
            {
                isDateExist = true;
                break;
            }
        }

        if (isDateExist)
        {
            Data* data = pack->mapData.value(date, NULL);
            Refs* refs = pack->mapRefs.value(date, NULL);
            if (data)
            {
                if (refs && refs->value(regionId.toInt(), -1) != -1)
                {
                    int refCount = refs->value(regionId.toInt());
                    refCount--;
                    if (!refCount)
                    {
                        refs->remove(regionId.toInt());
                        data->remove(regionId.toInt());
                    }
                    else
                    {
                        refs->insert(regionId.toInt(), refCount);
                    }
                }
                else
                {
                    data->remove(regionId.toInt());
                }
                if (!data->count())
                {
                    pack->mapData.remove(date);
                    pack->listDate.removeOne(date);
                    pack->mapRefs.remove(date);
                }
                result = true;
            }
        }
    }

    return result;
}

int dvDataTableController::indicatorCount()
{
    return m_listIndicators.count();
}

bool dvDataTableController::isExistData(const QVariant &indicatorId, const QString &date,
                                        const QVariant &regionId)
{
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            Data* data = pack->mapData.value(date, NULL);
            if (data)
            {
                return data->contains(regionId.toInt());
            }
        }
    }

    return false;
}

DV_INDICATOR *dvDataTableController::getIndicatorInfo(int index)
{
    if (index > -1 && index < indicatorCount())
    {
        return &m_listIndicators.at(index)->indicator;
    }
    return NULL;
}

Data *dvDataTableController::getIndicatorValuesAtDate(const QVariant &indicatorId,
                                                      const QString  &date)
{
    int index = findIndicator(indicatorId);
    if (index != -1)
    {
        dvDataPack* pack =  m_listIndicators.at(index);
        if (pack)
        {
            return pack->mapData.value(date, NULL);
        }
    }
    return NULL;
}

QString dvDataTableController::getStartDateForIndicator(const QVariant &indicatorId)
{
    QString date = QDate::currentDate().toString("yyyy-MM-dd");
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            if (pack->listDate.count())
            {
                //qDebug() << pack->listDate.count();
                pack->listDate.sort();
                date = pack->listDate.at(0);
            }
        }
    }

    return date;
}

QString dvDataTableController::getEndDateForIndicator(const QVariant &indicatorId)
{
    QString date = QDate::currentDate().toString("yyyy-MM-dd");
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            if (pack->listDate.count())
            {
                //qDebug() << pack->listDate.count();
                pack->listDate.sort();
                date = pack->listDate.at(pack->listDate.count() - 1);
            }
        }
    }

    return date;
}

int dvDataTableController::getDateCountForIndicator(const QVariant &indicatorId)
{
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            return pack->listDate.count();
        }
    }

    return 0;
}

QString dvDataTableController::getDateForIndicatorAt(const QVariant &indicatorId, int index)
{
    int ind = findIndicator(indicatorId);

    if (ind != -1)
    {
        dvDataPack* pack = m_listIndicators.at(ind);
        if (pack)
        {
            if (index >= 0 && index < pack->listDate.count())
            {
                pack->listDate.sort();
                return pack->listDate.at(index);
            }
        }
    }

    return QString("");
}

double dvDataTableController::getMaxIndicatorValueAtDate(const QVariant &indicatorId,
                                                         const QString &date)
{
    double value = 0.0;

    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            Data* data = pack->mapData.value(date);
            if (data)
            {
                QList<double> list = data->values();
                if (list.count())
                {
                    value = list.at(0);
                    for (int i = 1; i < list.count(); i++)
                    {
                        if (value < list.at(i))
                        {
                            value = list.at(i);
                        }
                    }
                }
            }
        }
    }

    return value;
}

double dvDataTableController::getMinIndicatorValueAtDate(const QVariant &indicatorId,
                                                         const QString &date)
{
    double value = 0.0;

    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            Data* data = pack->mapData.value(date);
            if (data)
            {
                QList<double> list = data->values();
                if (list.count())
                {
                    value = list.at(0);
                    for (int i = 1; i < list.count(); i++)
                    {
                        if (value > list.at(i))
                        {
                            value = list.at(i);
                        }
                    }
                }
            }
        }
    }

    return value;
}

double dvDataTableController::getPercentValueAtDateForRegion(const QVariant &indicatorId,
                                                             const QString &date,
                                                             const QVariant &regionId)
{
    double value = 0.0;
    double sum = 0.0;
    double percent = 0.0;

    int index = findIndicator(indicatorId);
    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            Data* data = pack->mapData.value(date);
            if (data)
            {
                foreach(int region, data->keys())
                {
                    sum += data->value(region, 0.0);
                    if (region == regionId.toInt())
                    {
                        value = data->value(region, 0.0);
                    }
                }
            }
        }

        if (sum > 0.0)
        {
            percent = value / sum * 100.0;
        }
    }

    return percent;
}

QStringList dvDataTableController::getListOfDatesForIndicator(const QVariant &indicatorId)
{
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            pack->listDate.sort();
            return pack->listDate;
        }
    }

    return QStringList();
}

dvMapPoints dvDataTableController::getAllDataForIndicator(const QVariant &indicatorId)
{
    dvMapPoints points;
    int index = findIndicator(indicatorId);

    if (index != -1)
    {
        dvDataPack* pack = m_listIndicators.at(index);
        if (pack)
        {
            pack->listDate.sort();
            double i = 0.0;
            foreach(QString date, pack->listDate)
            {
                Data* data = getIndicatorValuesAtDate(indicatorId, date);
                if (data)
                {
                    foreach(int region, data->keys())
                    {
                        if (!points.contains(region))
                        {
                            QVector<QPointF> newVector;
                            newVector.push_back(QPointF(i, data->value(region)));
                            points.insert(region, newVector);
                        }
                        else
                        {
                            points[region].push_back(QPointF(i, data->value(region)));
                        }
                        //qDebug() << date << " " << i << " " << data->value(region);
                    }
                }
                i += 1.0;
            }
        }
    }

    return points;
}


















































